home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2008 April / PCgo 2008-04 (DVD).iso / interface / contents / demoversionen_3846 / 13664 / files / Data1.cab / autospl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-22  |  27.6 KB  |  1,000 lines

  1. /******************************************************************/
  2. /*                                                                */
  3. /*                      TurboCAD for Windows                      */
  4. /*                   Copyright (c) 1993 - 2001                    */
  5. /*             International Microcomputer Software, Inc.         */
  6. /*                            (IMSI)                              */
  7. /*                      All rights reserved.                      */
  8. /*                                                                */
  9. /******************************************************************/
  10.  
  11. // AutoSpl.cpp : implementation file
  12. //
  13.  
  14. #include "stdafx.h"
  15. #include "MfcSplin.h"
  16. #include "AutoSpl.h"  // This class
  17. #include "SplPage.h"  // Property page class
  18. #include "GxIntf.h"   // TurboCAD interfaces (forward declarations)
  19. #include "Imsigx.h"   // TurboCAD interfaces
  20.  
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. // Standard variants
  28. COleVariant t(-1L, VT_BOOL);
  29. COleVariant f(0L, VT_BOOL);
  30. COleVariant missing((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  31.  
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CAutoSpline
  34.  
  35. const IID IID_IGraphic = 
  36.     {0x6A481109,0xE531,0x11CF,{0xA1,0x15,0x00,0xA0,0x24,0x15,0x8D,0xAF}};
  37.  
  38. IMPLEMENT_DYNCREATE(CAutoSpline, CCmdTarget)
  39.  
  40. CAutoSpline::CAutoSpline() :
  41.     m_pSplinePage(NULL)
  42. {
  43.     EnableAutomation();
  44.  
  45.     // To keep the application running as long as an OLE automation 
  46.     //    object is active, the constructor calls AfxOleLockApp.
  47.     
  48.     AfxOleLockApp();
  49. }
  50.  
  51. CAutoSpline::~CAutoSpline()
  52. {
  53.     // To terminate the application when all objects created with
  54.     //     with OLE automation, the destructor calls AfxOleUnlockApp.
  55.     
  56.     AfxOleUnlockApp();
  57. }
  58.  
  59.  
  60. void CAutoSpline::OnFinalRelease()
  61. {
  62.     // When the last reference for an automation object is released
  63.     // OnFinalRelease is called.  The base class will automatically
  64.     // deletes the object.  Add additional cleanup required for your
  65.     // object before calling the base class.
  66.  
  67.     CCmdTarget::OnFinalRelease();
  68. }
  69.  
  70.  
  71. BEGIN_MESSAGE_MAP(CAutoSpline, CCmdTarget)
  72.     //{{AFX_MSG_MAP(CAutoSpline)
  73.         // NOTE - the ClassWizard will add and remove mapping macros here.
  74.     //}}AFX_MSG_MAP
  75. END_MESSAGE_MAP()
  76.  
  77. BEGIN_DISPATCH_MAP(CAutoSpline, CCmdTarget)
  78.     //{{AFX_DISPATCH_MAP(CAutoSpline)
  79.     DISP_PROPERTY_EX(CAutoSpline, "ClassID", GetClassID, SetNotSupported, VT_BSTR)
  80.     DISP_PROPERTY_EX(CAutoSpline, "Description", GetDescription, SetNotSupported, VT_BSTR)
  81.     DISP_FUNCTION(CAutoSpline, "GetPropertyInfo", GetPropertyInfo, VT_I4, VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT)
  82.     DISP_FUNCTION(CAutoSpline, "GetPageInfo", GetPageInfo, VT_I4, VTS_DISPATCH VTS_PI4 VTS_PVARIANT)
  83.     DISP_FUNCTION(CAutoSpline, "GetWizardInfo", GetWizardInfo, VT_I4, VTS_PVARIANT)
  84.     DISP_FUNCTION(CAutoSpline, "GetEnumNames", GetEnumNames, VT_I4, VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  85.     DISP_FUNCTION(CAutoSpline, "PageControls", PageControls, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_I4 VTS_BOOL)
  86.     DISP_FUNCTION(CAutoSpline, "PageDone", PageDone, VT_EMPTY, VTS_DISPATCH VTS_PVARIANT)
  87.     DISP_FUNCTION(CAutoSpline, "PropertyPages", PropertyPages, VT_BOOL, VTS_DISPATCH VTS_PVARIANT)
  88.     DISP_FUNCTION(CAutoSpline, "Wizard", Wizard, VT_BOOL, VTS_DISPATCH VTS_PVARIANT)
  89.     DISP_FUNCTION(CAutoSpline, "OnGeometryChanged", OnGeometryChanged, VT_EMPTY, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  90.     DISP_FUNCTION(CAutoSpline, "OnGeometryChanging", OnGeometryChanging, VT_BOOL, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  91.     DISP_FUNCTION(CAutoSpline, "OnNewGraphic", OnNewGraphic, VT_BOOL, VTS_DISPATCH VTS_BOOL)
  92.     DISP_FUNCTION(CAutoSpline, "OnCopyGraphic", OnCopyGraphic, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_VARIANT)
  93.     DISP_FUNCTION(CAutoSpline, "OnPropertyChanged", OnPropertyChanged, VT_EMPTY, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  94.     DISP_FUNCTION(CAutoSpline, "OnPropertyChanging", OnPropertyChanging, VT_BOOL, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  95.     DISP_FUNCTION(CAutoSpline, "OnPropertyGet", OnPropertyGet, VT_EMPTY, VTS_DISPATCH VTS_I4)
  96.     DISP_FUNCTION(CAutoSpline, "Draw", Draw, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_PVARIANT)
  97.     DISP_FUNCTION(CAutoSpline, "Regen", Regen, VT_EMPTY, VTS_DISPATCH)
  98.     DISP_FUNCTION(CAutoSpline, "Initialize", Initialize, VT_BOOL, VTS_DISPATCH)
  99.     //}}AFX_DISPATCH_MAP
  100. END_DISPATCH_MAP()
  101.  
  102. // Note: we add support for IID_ISmartObjectServer to support typesafe binding
  103. //  from VBA.  This IID must match the GUID that is attached to the 
  104. //  dispinterface in the .ODL file.
  105.  
  106. // {6A481303-E531-11CF-A115-00A024158DAF}
  107. static const IID IID_ISmartObjectServer =
  108. {0x6A481303,0xE531,0x11CF,{0xA1,0x15,0x00,0xA0,0x24,0x15,0x8D,0xAF}};
  109.  
  110. BEGIN_INTERFACE_MAP(CAutoSpline, CCmdTarget)
  111.     INTERFACE_PART(CAutoSpline, IID_ISmartObjectServer, Dispatch)
  112. END_INTERFACE_MAP()
  113.  
  114. // {7724BB46-B671-11D0-9B3B-444553540000}
  115. IMPLEMENT_OLECREATE(CAutoSpline, "MFCSpline.Spline", 0x7724bb46, 0xb671, 0x11d0, 0x9b, 0x3b, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
  116.  
  117. /////////////////////////////////////////////////////////////////////////////
  118. // CAutoSpline message handlers
  119.  
  120. BSTR CAutoSpline::GetDescription() 
  121. {
  122.     // Get the description from the resource
  123.     CString strResult;
  124.     strResult.LoadString(IDS_AUTOSPLINE_DESCRIPTION);
  125.  
  126.     return strResult.AllocSysString();
  127. }
  128.  
  129. BSTR CAutoSpline::GetClassID() 
  130. {
  131.     // Convert our GUID (see IMPLEMENT_OLECREATE macro) to a string
  132.     LPOLESTR olestr;
  133.     HRESULT hRes = ::StringFromCLSID(guid, &olestr);
  134.     if (FAILED(hRes))
  135.         return NULL;
  136.  
  137.     BSTR bstr = ::SysAllocString(olestr);
  138.     CoTaskMemFree(olestr);
  139.     return bstr;
  140. }
  141.  
  142. const long VT_INTEGER_ENUM = VT_I2 + 100;
  143. const long VT_LONG_ENUM = VT_I4 + 100;
  144. const long VT_STRING_ENUM = VT_BSTR + 100;
  145.  
  146.  
  147. // define 6 properties for Spline object
  148. const long nProperties = 6;
  149.  
  150. enum PropertyIDs 
  151. {
  152.    idSplineType = 1,
  153.    idSegments = 2,
  154.    idShowFrame = 3,
  155.    idShowControlPoints = 4,
  156.    idSmoothing = 5,
  157.    idFrameColor = 6    
  158. };
  159.  
  160. enum SplineTypes 
  161. {
  162.     typeCubicSpline = 0
  163. };
  164.  
  165. long CAutoSpline::GetPropertyInfo(VARIANT FAR* Names, VARIANT FAR* Types, VARIANT FAR* IDs, VARIANT FAR* Defaults) 
  166. {
  167.      ASSERT(Names->vt == (VT_ARRAY|VT_BSTR));
  168.     ASSERT(Types->vt == (VT_ARRAY|VT_I4));
  169.     ASSERT(IDs->vt == (VT_ARRAY|VT_I4));
  170.     ASSERT(Defaults->vt == (VT_ARRAY|VT_VARIANT));
  171.  
  172.      SAFEARRAYBOUND bound = { nProperties, 0 };
  173.     if (FAILED(::SafeArrayRedim(Names->parray, &bound)))
  174.         return 0;
  175.     if (FAILED(::SafeArrayRedim(Types->parray, &bound)))
  176.         return 0;
  177.     if (FAILED(::SafeArrayRedim(IDs->parray, &bound)))
  178.         return 0;
  179.     if (FAILED(::SafeArrayRedim(Defaults->parray, &bound)))
  180.         return 0;
  181.  
  182.     BSTR* rgNames;
  183.     long* rgTypes;
  184.     long* rgIDs;
  185.     VARIANT* rgDefaults; 
  186.     long lReturn = 0;
  187.     if (SUCCEEDED(::SafeArrayAccessData(Names->parray, (void**)&rgNames)))
  188.     {
  189.         if (SUCCEEDED(::SafeArrayAccessData(Types->parray, (void**)&rgTypes)))
  190.         {
  191.             if (SUCCEEDED(::SafeArrayAccessData(IDs->parray, (void**)&rgIDs)))
  192.             {
  193.                 if (SUCCEEDED(::SafeArrayAccessData(Defaults->parray, (void**)&rgDefaults)))
  194.                 {
  195.                     
  196.                     CString strStr;
  197.                     strStr.LoadString(IDS_PROPERTYSPLINETYPE);
  198.                     rgNames[0] = ::SysAllocString(strStr.AllocSysString());
  199.                     rgTypes[0] = VT_INTEGER_ENUM;
  200.                     rgIDs[0] = idSplineType;
  201.                     rgDefaults[0].vt = VT_I2;
  202.                     rgDefaults[0].iVal = typeCubicSpline;
  203.                     
  204.                     strStr.Empty();
  205.                     strStr.LoadString(IDS_PROPERTYSEGMENTSCOUNT);
  206.                     rgNames[1] = ::SysAllocString(strStr.AllocSysString());
  207.                     rgTypes[1] = VT_I4;
  208.                     rgIDs[1] = idSegments;
  209.                     rgDefaults[1].vt = VT_I4;
  210.                     rgDefaults[1].lVal = 16;
  211.  
  212.                     strStr.Empty();
  213.                     strStr.LoadString(IDS_PROPERTYSHOWFRAME);
  214.                     rgNames[2] = ::SysAllocString(strStr.AllocSysString());
  215.                     rgTypes[2] = VT_BOOL;
  216.                     rgIDs[2] = idShowFrame;
  217.                     rgDefaults[2].vt = VT_BOOL;
  218.                     rgDefaults[2].boolVal = FALSE;
  219.  
  220.                     strStr.Empty();
  221.                     strStr.LoadString(IDS_PROPERTYSHOWCONTROLPOINTS);
  222.                     rgNames[3] = ::SysAllocString(strStr.AllocSysString());
  223.                     rgTypes[3] = VT_BOOL;
  224.                     rgIDs[3] = idShowControlPoints;
  225.                     rgDefaults[3].vt = VT_BOOL;
  226.                     rgDefaults[3].boolVal = FALSE;
  227.  
  228.                     strStr.Empty();
  229.                     strStr.LoadString(IDS_PROPERTYSMOOTHING);
  230.                     rgNames[4] = ::SysAllocString(strStr.AllocSysString());
  231.                     rgTypes[4] = VT_BOOL;
  232.                     rgIDs[4] = idSmoothing;
  233.                     rgDefaults[4].vt = VT_BOOL;
  234.                     rgDefaults[4].boolVal = FALSE;
  235.  
  236.                     strStr.Empty();
  237.                     strStr.LoadString(IDS_PROPERTYFRAMECOLOR);
  238.                     rgNames[5] = ::SysAllocString(strStr.AllocSysString());
  239.                     rgTypes[5] = VT_I4;
  240.                     rgIDs[5] = idFrameColor;
  241.                     rgDefaults[5].vt = VT_I4;
  242.                     rgDefaults[5].lVal = RGB(255, 0, 0);
  243.  
  244.                     ::SafeArrayUnaccessData(Defaults->parray);
  245.                     strStr.Empty();
  246.  
  247.                     lReturn = nProperties;
  248.                 }
  249.                 ::SafeArrayUnaccessData(IDs->parray);
  250.             }
  251.             ::SafeArrayUnaccessData(Types->parray);
  252.         }
  253.         ::SafeArrayUnaccessData(Names->parray);
  254.     }
  255.     return lReturn;
  256. }
  257.  
  258. enum StockPages {
  259.     PP_STOCK_PEN = 1,
  260.     PP_STOCK_BRUSH = 2,
  261.     PP_STOCK_TEXT = 4,
  262.     PP_STOCK_INSERT = 8,
  263.     PP_STOCK_VIEWPORT = 16,
  264.     PP_STOCK_AUTO = 32
  265. };
  266.  
  267. long CAutoSpline::GetPageInfo(LPDISPATCH /*AGraphic*/, long* StockPages, VARIANT FAR* Names) 
  268. {
  269.     ASSERT(StockPages != NULL);
  270.      ASSERT(Names->vt == (VT_ARRAY|VT_BSTR));
  271.  
  272.     // Request pen page and auto page
  273.     *StockPages = PP_STOCK_PEN | PP_STOCK_AUTO;
  274.  
  275.      SAFEARRAYBOUND bound = { 1, 0 };
  276.     if (FAILED(::SafeArrayRedim(Names->parray, &bound)))
  277.         return 0;
  278.  
  279.     CString strCaption;
  280.     strCaption.LoadString(IDS_AUTOSPLINE_CAPTION);
  281.     BSTR bstrCaption = strCaption.AllocSysString();
  282.  
  283.     long lIndex = 0;
  284.     if (FAILED(SafeArrayPutElement(Names->parray, &lIndex, (void*)bstrCaption)))
  285.     {
  286.         ::SysFreeString(bstrCaption);
  287.         return 0;
  288.     }
  289.     return 1;
  290. }
  291.  
  292. long CAutoSpline::GetWizardInfo(VARIANT FAR* Names) 
  293. {
  294.     // No wizards, nothing to do
  295.     return 0;
  296. }
  297.  
  298. long CAutoSpline::GetEnumNames(long PropID, VARIANT FAR* Names, VARIANT FAR* Values) 
  299. {
  300.     if (PropID != idSplineType)
  301.         return 0;
  302.  
  303.      ASSERT(Names->vt == (VT_ARRAY|VT_BSTR));
  304.      ASSERT(Values->vt == (VT_ARRAY|VT_VARIANT));
  305.  
  306.     // TODO: Associate each spline type name and value
  307.     return 0;
  308. }
  309.  
  310. BOOL CAutoSpline::PageControls(LPDISPATCH ThisRegenMethod, LPDISPATCH AGraphic, long PageNumber, BOOL SaveProperties) 
  311. {
  312.     IGraphic* pIGraphic = NULL;
  313.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  314.         return FALSE;
  315.  
  316.     BOOL bReturn = FALSE;
  317.     Properties* pProps = NULL;
  318.     Property* pProp;
  319.     COleVariant varIndex, varValue;
  320.     CString strStr;
  321.  
  322.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  323.     {
  324.         if (SaveProperties)
  325.         {
  326.             if (m_pSplinePage != NULL)
  327.             {
  328.                 // Note: the following can fail (for non-spline graphics)
  329.                 strStr.LoadString(IDS_PROPERTYSEGMENTSCOUNT);
  330.                 varIndex = LPCTSTR(strStr);
  331.  
  332.                 if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  333.                 {
  334.                     varValue = (const long)m_pSplinePage->m_nSegments;
  335.                     pProp->put_Value(0, &varValue);
  336.                     pProp->Release();
  337.                     varValue.Clear();
  338.                 }
  339.                 strStr.Empty();
  340.                 strStr.LoadString(IDS_PROPERTYSHOWCONTROLPOINTS);
  341.                 varIndex = LPCTSTR(strStr);
  342.                 if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  343.                 {
  344.                     // MFC has no overloaded operator for BOOLs!
  345.                     varValue.vt = VT_BOOL;
  346.                     varValue.boolVal = m_pSplinePage->m_bControlPoints;
  347.                     pProp->put_Value(0, &varValue);
  348.                     pProp->Release();
  349.                     varValue.Clear();
  350.                 }
  351.                 strStr.Empty();
  352.                 strStr.LoadString(IDS_PROPERTYSHOWFRAME);
  353.                 varIndex = LPCTSTR(strStr);
  354.                 if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  355.                 {
  356.                     varValue.vt = VT_BOOL;
  357.                     varValue.boolVal = m_pSplinePage->m_bFrame;
  358.                     pProp->put_Value(0, &varValue);
  359.                     pProp->Release();
  360.                     varValue.Clear();
  361.                 }
  362.                 strStr.Empty();
  363.                 strStr.LoadString(IDS_PROPERTYSMOOTHING);
  364.                 varIndex = LPCTSTR(strStr);
  365.                 if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  366.                 {
  367.                     varValue.vt = VT_BOOL;
  368.                     varValue.boolVal = m_pSplinePage->m_bSmoothing;
  369.                     pProp->put_Value(0, &varValue);
  370.                     pProp->Release();
  371.                     varValue.Clear();
  372.                 }
  373.                 bReturn = TRUE;
  374.             }
  375.         }
  376.         else
  377.         {
  378.             ASSERT(m_pSplinePage == NULL);
  379.             m_pSplinePage = new CSplinePage();
  380.  
  381.             // Note: the following can fail (for indeterminate values)
  382.             strStr.LoadString(IDS_PROPERTYSEGMENTSCOUNT);
  383.             varIndex = LPCTSTR(strStr);
  384.             if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  385.             {
  386.                 if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  387.                     varValue.vt == VT_I4)
  388.                     m_pSplinePage->m_nSegments = varValue.lVal;
  389.                 pProp->Release();
  390.                 varValue.Clear();
  391.             }
  392.             strStr.Empty();
  393.             strStr.LoadString(IDS_PROPERTYSHOWCONTROLPOINTS);
  394.             varIndex = LPCTSTR(strStr);
  395.             if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  396.             {
  397.                 if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  398.                     varValue.vt == VT_BOOL)
  399.                     m_pSplinePage->m_bControlPoints = varValue.boolVal;
  400.                 pProp->Release();
  401.                 varValue.Clear();
  402.             }
  403.             strStr.Empty();
  404.             strStr.LoadString(IDS_PROPERTYSHOWFRAME);
  405.             varIndex = LPCTSTR(strStr);
  406.             if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  407.             {
  408.                 if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  409.                     varValue.vt == VT_BOOL)
  410.                     m_pSplinePage->m_bFrame = varValue.boolVal;
  411.                 pProp->Release();
  412.                 varValue.Clear();
  413.             }
  414.             strStr.Empty();
  415.             strStr.LoadString(IDS_PROPERTYSMOOTHING);
  416.             varIndex = LPCTSTR(strStr);
  417.             if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  418.             {
  419.                 if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  420.                     varValue.vt == VT_BOOL)
  421.                     m_pSplinePage->m_bSmoothing = varValue.boolVal;
  422.                 pProp->Release();
  423.                 varValue.Clear();
  424.             }
  425.             bReturn = TRUE;
  426.         }
  427.         pProps->Release();
  428.     }
  429.  
  430.     pIGraphic->Release();
  431.     return bReturn;
  432. }
  433.  
  434. void CAutoSpline::PageDone(LPDISPATCH ThisRegenMethod, VARIANT FAR* PageNumber) 
  435. {
  436.     // We're finished with the page
  437.     delete m_pSplinePage;
  438.     m_pSplinePage = NULL;
  439. }
  440.  
  441. BOOL CAutoSpline::PropertyPages(LPDISPATCH ThisRegenMethod, VARIANT FAR* PageNumber) 
  442. {
  443.     if (m_pSplinePage == NULL)
  444.         return FALSE;
  445.  
  446.     // Run the dialog and get the results
  447.     int nResult = m_pSplinePage->DoModal();
  448.     return (nResult == IDOK);
  449. }
  450.  
  451. BOOL CAutoSpline::Wizard(LPDISPATCH ThisRegenMethod, VARIANT FAR* WizardNumber) 
  452. {
  453.     // No wizards, so just return FALSE.
  454.     return FALSE;
  455. }
  456.  
  457. void CAutoSpline::OnGeometryChanged(LPDISPATCH AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew) 
  458. {
  459. }
  460.  
  461. BOOL CAutoSpline::OnGeometryChanging(LPDISPATCH AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew) 
  462. {
  463.     // OK to change our geometry, so just return TRUE.
  464.     return TRUE;
  465. }
  466.  
  467. BOOL CAutoSpline::OnNewGraphic(LPDISPATCH AGraphic, BOOL Copy) 
  468. {
  469.     // Return FALSE on failure.
  470.     // For copies, usually do nothing.
  471.     if (Copy)
  472.         return TRUE;
  473.  
  474.     // Add vertices, etc. for new graphic here.
  475.  
  476.     // TODO: Do nothing here.
  477.     IGraphic* pIGraphic = NULL;
  478.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  479.         return FALSE;
  480.  
  481.     Vertices* pVerts = NULL;
  482.     IVertex* pIVertex = NULL;
  483.  
  484.     
  485.     if (SUCCEEDED(pIGraphic->get_Vertices(&pVerts)))
  486.     {
  487.         COleVariant x;
  488.         COleVariant y;
  489.         COleVariant z(0.0);
  490.  
  491.         BOOL bFirst = TRUE;
  492.         const double points[4*2] = { 0.0, 0.0, 1.0, 1.0, 2.0, 1.0, 3.0, 0.0 };
  493.         for (int i = 0; i < 4*2; )
  494.         {
  495.             x = points[i++];
  496.             y = points[i++];
  497.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  498.                 bFirst ? &f : &t /*penDown*/, 
  499.                 &t /*selectable*/,
  500.                 &t /*snappable*/,
  501.                 &t /*editable*/, 
  502.                 &t /*linkable*/,
  503.                 &f /*calculated*/,
  504.                 &missing /*before*/,
  505.                 &missing /*after*/,
  506.                 &pIVertex)))
  507.                 pIVertex->Release();
  508.             bFirst = FALSE;
  509.         }
  510.     }
  511.     pIGraphic->Release();
  512.     return TRUE;
  513. }
  514.  
  515. BOOL CAutoSpline::OnCopyGraphic(LPDISPATCH DestGraphic, LPDISPATCH SourceGraphic, VARIANT*) 
  516. {
  517.     // Return FALSE on failure.
  518.     return TRUE;
  519. }
  520.  
  521. void CAutoSpline::OnPropertyChanged(LPDISPATCH AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew) 
  522. {
  523. }
  524.  
  525. BOOL CAutoSpline::OnPropertyChanging(LPDISPATCH AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew) 
  526. {
  527.     // OK to change all of our properties, so just return TRUE.
  528.     return TRUE;
  529. }
  530.  
  531. void CAutoSpline::OnPropertyGet(LPDISPATCH AGraphic, long PropID) 
  532. {
  533.     // No special recalculating of properties needed.
  534. }
  535.  
  536. BOOL CAutoSpline::Draw(LPDISPATCH AGraphic, LPDISPATCH AView, VARIANT FAR* AMatrix) 
  537. {
  538.     // We don't handle special drawing, so just return FALSE.
  539.     return FALSE;
  540. }
  541.  
  542. BOOL GetVertexXYZ(IGraphic* pIGraphic, const long lVertex, double& x, double& y, double& z)
  543. {
  544.     IVertex* pIVertex = NULL;
  545.     Vertices* pVerts = NULL;
  546.     BOOL bSuccess = FALSE;
  547.     if (SUCCEEDED(pIGraphic->get_Vertices(&pVerts)))
  548.     {
  549.         COleVariant varIndex = lVertex;
  550.         if (SUCCEEDED(pVerts->get_Item(&varIndex, &pIVertex)))
  551.         {
  552.             if (SUCCEEDED(pIVertex->get_X(&x)) &&
  553.                 SUCCEEDED(pIVertex->get_Y(&y)) &&
  554.                 SUCCEEDED(pIVertex->get_Z(&z)))
  555.                 bSuccess = TRUE;
  556.             pIVertex->Release();
  557.         }
  558.         pVerts->Release();
  559.     }
  560.     return bSuccess;
  561. }
  562.  
  563. const long GF_COSMETIC = 128;
  564.  
  565. struct BezierCoeffs
  566. {
  567.     double t, tSquared, tCubed, 
  568.         oneMinusT, oneMinusTSquared, oneMinusTCubed;
  569. };
  570.  
  571. double BezierEvaluate(const double v[4], const BezierCoeffs& c)
  572. {
  573.     double vResult = c.oneMinusTCubed * v[0] + 
  574.         3.0 * c.t * c.oneMinusTSquared * v[1] +
  575.         3.0 * c.tSquared * c.oneMinusT * v[2] +
  576.         c.tCubed * v[3];
  577.     return vResult;
  578. }
  579.  
  580. void CAutoSpline::Regen(LPDISPATCH AGraphic) 
  581. {
  582.     IGraphic* pIGraphic = NULL;
  583.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  584.         return;
  585.  
  586.     long lockCount = 0;
  587.     CString strStr;
  588.  
  589.     if (SUCCEEDED(pIGraphic->RegenLock(&lockCount)))
  590.     {
  591.         if (lockCount == 0)
  592.         {
  593.             // TODO:  All the curve processing goes here
  594.             // build spline
  595.             Graphics* pGraphics = NULL;
  596.             IGraphic* pChild = NULL;
  597.             IVertex* pIVertex = NULL;
  598.             if (SUCCEEDED(pIGraphic->get_Graphics(&pGraphics)))
  599.             {
  600.                 COleVariant flags = (const long)GF_COSMETIC;
  601.                 // clear all child graphics
  602.                 pGraphics->Clear(&flags);
  603.  
  604.                 long nSegments = 16;
  605.                 Properties* pProps = NULL;
  606.                 Property* pProp = NULL;
  607.                 COleVariant varIndex, varValue;
  608.                 if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  609.                 {
  610.                     // in this example we process only one property (Segments count)
  611.                     // add your code to process other properties (ShowFrame, ShowControlPoints,
  612.                     // Smoothing, FrameColor)
  613.                     strStr.LoadString(IDS_PROPERTYSEGMENTSCOUNT);
  614.                     varIndex = LPCTSTR(strStr);
  615.                     if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  616.                     {
  617.                         if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  618.                             varValue.vt == VT_I4)
  619.                         {
  620.                             nSegments = varValue.lVal;
  621.                             if (nSegments > 200)
  622.                                 nSegments = 200;
  623.                             else if (nSegments < 2)
  624.                                 nSegments = 2;
  625.                         }
  626.                         pProp->Release();
  627.                     }
  628.                     pProps->Release();
  629.                 }
  630.  
  631.                 double px[4] = { 0.0 };
  632.                 double py[4] = { 0.0 };
  633.                 double pz[4] = { 0.0 };
  634.                 for (int i = 0; i < 4; ++i)
  635.                     GetVertexXYZ(pIGraphic, i, px[i], py[i], pz[i]);
  636.  
  637.                 if (SUCCEEDED(pGraphics->Add(
  638.                     &missing /*GraphicType*/,
  639.                     &missing /*RegenMethod*/,
  640.                     &missing /*Inherit*/, 
  641.                     &missing /*Style*/,
  642.                     &missing /*Before*/,
  643.                     &missing /*After*/,                    
  644.                     &pChild)))
  645.                 {
  646.                     pChild->put_Cosmetic(TRUE);
  647.  
  648.                     COleVariant x, y, z;
  649.                     Vertices* pVerts = NULL;
  650.                     IVertex* pIVertex = NULL;
  651.                     if (SUCCEEDED(pChild->get_Vertices(&pVerts)))
  652.                     {
  653.                         BezierCoeffs c;
  654.                         BOOL bFirst = TRUE;
  655.                         for (long lt = 0; lt <= nSegments; ++lt)
  656.                         {
  657.                             c.t = (lt == nSegments) ? 1.0 : (double)lt/double(nSegments);
  658.                             c.tSquared = c.t * c.t;
  659.                             c.tCubed = c.tSquared * c.t;
  660.                             c.oneMinusT = 1.0 - c.t;
  661.                             c.oneMinusTSquared = c.oneMinusT * c.oneMinusT;
  662.                             c.oneMinusTCubed = c.oneMinusTSquared * c.oneMinusT;
  663.  
  664.                             x = BezierEvaluate(px, c);
  665.                             y = BezierEvaluate(py, c);
  666.                             z = BezierEvaluate(pz, c);
  667.  
  668.                             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  669.                                 bFirst ? &f : &t /*penDown*/, 
  670.                                 &f /*selectable*/,
  671.                                 &f /*snappable*/,
  672.                                 &f /*editable*/, 
  673.                                 &f /*linkable*/,
  674.                                 &f /*calculated*/,
  675.                                 &missing /*before*/,
  676.                                 &missing /*after*/,
  677.                                 &pIVertex)))
  678.                                 pIVertex->Release();
  679.                             bFirst = FALSE;
  680.                         }
  681.                         pVerts->Release();
  682.                     }
  683.                     pChild->Release();
  684.                 }
  685.                 pGraphics->Release();
  686.             }
  687.         }
  688.         pIGraphic->RegenUnlock(&missing);
  689.     }
  690.     pIGraphic->Release();
  691. }
  692.  
  693. BOOL CAutoSpline::Initialize(LPDISPATCH ThisRegenMethod) 
  694. {
  695.     // TODO: Add your dispatch handler code here
  696.     return TRUE;
  697. }
  698.  
  699. // DUAL_SUPPORT_START
  700.  
  701. // delegate standard IDispatch methods to MFC IDispatch implementation
  702. DELEGATE_DUAL_INTERFACE(CAutoSpline, DualSpline)
  703.  
  704. // Our method and property functions can generally just
  705. // delegate back to the methods we generated using 
  706. // ClassWizard. However, if we set up properties to 
  707. // access variables directly, we will need to write the
  708. //  code to get/put the value into the variable.
  709. STDMETHODIMP CAutoSpline::XDualSpline::get_Description(BSTR FAR* retval)
  710. {
  711.     if (retval == NULL)
  712.         return E_POINTER;
  713.  
  714.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  715.  
  716.     TRY_DUAL(IID_ISmartObjectServer)
  717.     {
  718.         *retval = pThis->GetDescription();
  719.         return S_OK;
  720.     }
  721.     CATCH_ALL_DUAL
  722. }
  723.  
  724. STDMETHODIMP CAutoSpline::XDualSpline::get_ClassID(BSTR FAR* retval)
  725. {
  726.     if (retval == NULL)
  727.         return E_POINTER;
  728.  
  729.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  730.  
  731.     TRY_DUAL(IID_ISmartObjectServer)
  732.     {
  733.         *retval = pThis->GetClassID();
  734.         return S_OK;
  735.     }
  736.     CATCH_ALL_DUAL
  737. }
  738.  
  739. STDMETHODIMP CAutoSpline::XDualSpline::GetPropertyInfo(VARIANT FAR* Names, VARIANT FAR* Types, VARIANT FAR* IDs, VARIANT FAR* Defaults, long FAR* retval)
  740. {
  741.     if (retval == NULL)
  742.         return E_POINTER;
  743.  
  744.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  745.  
  746.     TRY_DUAL(IID_ISmartObjectServer)
  747.     {
  748.         *retval = pThis->GetPropertyInfo(Names, Types, IDs, Defaults);
  749.         return S_OK;
  750.     }
  751.     CATCH_ALL_DUAL
  752. }
  753.  
  754. STDMETHODIMP CAutoSpline::XDualSpline::GetPageInfo(IDispatch * AGraphic, long FAR* StockPages, VARIANT FAR* Names, long FAR* retval)
  755. {
  756.     if (retval == NULL)
  757.         return E_POINTER;
  758.  
  759.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  760.  
  761.     TRY_DUAL(IID_ISmartObjectServer)
  762.     {
  763.         *retval = pThis->GetPageInfo(AGraphic, StockPages, Names);
  764.         return S_OK;
  765.     }
  766.     CATCH_ALL_DUAL
  767. }
  768.  
  769. STDMETHODIMP CAutoSpline::XDualSpline::GetWizardInfo(VARIANT FAR* Names, long FAR* retval)
  770. {
  771.     if (retval == NULL)
  772.         return E_POINTER;
  773.  
  774.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  775.  
  776.     TRY_DUAL(IID_ISmartObjectServer)
  777.     {
  778.         *retval = pThis->GetWizardInfo(Names);
  779.         return S_OK;
  780.     }
  781.     CATCH_ALL_DUAL
  782. }
  783.  
  784. STDMETHODIMP CAutoSpline::XDualSpline::GetEnumNames(long PropID, VARIANT FAR* Names, VARIANT FAR* Values, long FAR* retval)
  785. {
  786.     if (retval == NULL)
  787.         return E_POINTER;
  788.  
  789.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  790.  
  791.     TRY_DUAL(IID_ISmartObjectServer)
  792.     {
  793.         *retval = pThis->GetEnumNames(PropID, Names, Values);
  794.         return S_OK;
  795.     }
  796.     CATCH_ALL_DUAL
  797. }
  798.  
  799. STDMETHODIMP CAutoSpline::XDualSpline::PageControls(IDispatch* ThisRegenMethod, IDispatch * AGraphic, long PageNumber, VARIANT_BOOL SaveProperties, VARIANT_BOOL* retval)
  800. {
  801.     if (retval == NULL)
  802.         return E_POINTER;
  803.  
  804.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  805.  
  806.     TRY_DUAL(IID_ISmartObjectServer)
  807.     {
  808.         *retval = pThis->PageControls(ThisRegenMethod, AGraphic, PageNumber, SaveProperties);
  809.         return S_OK;
  810.     }
  811.     CATCH_ALL_DUAL
  812. }
  813.  
  814. STDMETHODIMP CAutoSpline::XDualSpline::PageDone(IDispatch * ThisRegenMethod, VARIANT FAR* PageNumber)
  815. {
  816.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  817.  
  818.     TRY_DUAL(IID_ISmartObjectServer)
  819.     {
  820.         pThis->PageDone(ThisRegenMethod, PageNumber);
  821.         return S_OK;
  822.     }
  823.     CATCH_ALL_DUAL
  824. }
  825.  
  826. STDMETHODIMP CAutoSpline::XDualSpline::PropertyPages(IDispatch* ThisRegenMethod, VARIANT FAR* PageNumber, VARIANT_BOOL* retval)
  827. {
  828.     if (retval == NULL)
  829.         return E_POINTER;
  830.  
  831.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  832.  
  833.     TRY_DUAL(IID_ISmartObjectServer)
  834.     {
  835.         *retval = pThis->PropertyPages(ThisRegenMethod, PageNumber);
  836.         return S_OK;
  837.     }
  838.     CATCH_ALL_DUAL
  839. }
  840.  
  841. STDMETHODIMP CAutoSpline::XDualSpline::Wizard(IDispatch* ThisRegenMethod, VARIANT FAR* WizardNumber, VARIANT_BOOL* retval)
  842. {
  843.     if (retval == NULL)
  844.         return E_POINTER;
  845.  
  846.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  847.  
  848.     TRY_DUAL(IID_ISmartObjectServer)
  849.     {
  850.         *retval = pThis->Wizard(ThisRegenMethod, WizardNumber);
  851.         return S_OK;
  852.     }
  853.     CATCH_ALL_DUAL
  854. }
  855.  
  856. STDMETHODIMP CAutoSpline::XDualSpline::OnGeometryChanged(IDispatch * AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew)
  857. {
  858.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  859.  
  860.     TRY_DUAL(IID_ISmartObjectServer)
  861.     {
  862.         pThis->OnGeometryChanged(AGraphic, GeomID, ParamOld, ParamNew);
  863.         return S_OK;
  864.     }
  865.     CATCH_ALL_DUAL
  866. }
  867.  
  868. STDMETHODIMP CAutoSpline::XDualSpline::OnGeometryChanging(IDispatch * AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew, VARIANT_BOOL* retval)
  869. {
  870.     if (retval == NULL)
  871.         return E_POINTER;
  872.  
  873.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  874.  
  875.     TRY_DUAL(IID_ISmartObjectServer)
  876.     {
  877.         *retval = pThis->OnGeometryChanging(AGraphic, GeomID, ParamOld, ParamNew);
  878.         return S_OK;
  879.     }
  880.     CATCH_ALL_DUAL
  881. }
  882.  
  883. STDMETHODIMP CAutoSpline::XDualSpline::OnNewGraphic(IDispatch * AGraphic, VARIANT_BOOL Copy, VARIANT_BOOL* retval)
  884. {
  885.     if (retval == NULL)
  886.         return E_POINTER;
  887.  
  888.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  889.  
  890.     TRY_DUAL(IID_ISmartObjectServer)
  891.     {
  892.         *retval = pThis->OnNewGraphic(AGraphic, Copy);
  893.         return S_OK;
  894.     }
  895.     CATCH_ALL_DUAL
  896. }
  897.  
  898. STDMETHODIMP CAutoSpline::XDualSpline::OnCopyGraphic(IDispatch* CopyGraphic, IDispatch* SourceGraphic, VARIANT* Matrix, VARIANT_BOOL* retval)
  899. {
  900.     if (retval == NULL)
  901.         return E_POINTER;
  902.  
  903.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  904.  
  905.     TRY_DUAL(IID_ISmartObjectServer)
  906.     {
  907.         *retval = pThis->OnCopyGraphic(CopyGraphic, SourceGraphic, Matrix);
  908.         return S_OK;
  909.     }
  910.     CATCH_ALL_DUAL
  911. }
  912.  
  913. STDMETHODIMP CAutoSpline::XDualSpline::OnPropertyChanged(IDispatch * AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew)
  914. {
  915.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  916.  
  917.     TRY_DUAL(IID_ISmartObjectServer)
  918.     {
  919.         pThis->OnPropertyChanged(AGraphic, PropID, ValueOld, ValueNew);
  920.         return S_OK;
  921.     }
  922.     CATCH_ALL_DUAL
  923. }
  924.  
  925. STDMETHODIMP CAutoSpline::XDualSpline::OnPropertyChanging(IDispatch * AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew, VARIANT_BOOL* retval)
  926. {
  927.     if (retval == NULL)
  928.         return E_POINTER;
  929.  
  930.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  931.  
  932.     TRY_DUAL(IID_ISmartObjectServer)
  933.     {
  934.         *retval = pThis->OnPropertyChanging(AGraphic, PropID, ValueOld, ValueNew);
  935.         return S_OK;
  936.     }
  937.     CATCH_ALL_DUAL
  938. }
  939.  
  940. STDMETHODIMP CAutoSpline::XDualSpline::OnPropertyGet(IDispatch * AGraphic, long PropID)
  941. {
  942.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  943.  
  944.     TRY_DUAL(IID_ISmartObjectServer)
  945.     {
  946.         pThis->OnPropertyGet(AGraphic, PropID);
  947.         return S_OK;
  948.     }
  949.     CATCH_ALL_DUAL
  950. }
  951.  
  952. STDMETHODIMP CAutoSpline::XDualSpline::Draw(IDispatch * AGraphic, IDispatch * AView, VARIANT FAR* AMatrix, VARIANT_BOOL* retval)
  953. {
  954.     if (retval == NULL)
  955.         return E_POINTER;
  956.  
  957.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  958.  
  959.     TRY_DUAL(IID_ISmartObjectServer)
  960.     {
  961.         *retval = pThis->Draw(AGraphic, AView, AMatrix);
  962.         return S_OK;
  963.     }
  964.     CATCH_ALL_DUAL
  965. }
  966.  
  967. STDMETHODIMP CAutoSpline::XDualSpline::Regen(IDispatch* AGraphic)
  968. {
  969.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  970.  
  971.     TRY_DUAL(IID_ISmartObjectServer)
  972.     {
  973.         pThis->Regen(AGraphic);
  974.         return S_OK;
  975.     }
  976.     CATCH_ALL_DUAL
  977. }
  978.  
  979. STDMETHODIMP CAutoSpline::XDualSpline::Initialize(IDispatch* ThisRegenMethod, VARIANT_BOOL* retval)
  980. {
  981.     if (retval == NULL)
  982.         return E_POINTER;
  983.  
  984.     METHOD_PROLOGUE(CAutoSpline, DualSpline)
  985.  
  986.     TRY_DUAL(IID_ISmartObjectServer)
  987.     {
  988.         *retval = pThis->Initialize(ThisRegenMethod);
  989.         return S_OK;
  990.     }
  991.     CATCH_ALL_DUAL
  992. }
  993.  
  994.  
  995. // Implement ISupportErrorInfo to indicate we support the 
  996. // OLE Automation error handler.
  997. IMPLEMENT_DUAL_ERRORINFO(CAutoSpline, IID_ISmartObjectServer)
  998.  
  999. // DUAL_SUPPORT_END
  1000.